package com.atguigu.yygh.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.common.exception.YyghException;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.enums.PaymentStatusEnum;
import com.atguigu.yygh.hosp.client.ScheduleFeignClient;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.order.PaymentInfo;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.mq.MqConst;
import com.atguigu.yygh.mq.RabbitService;
import com.atguigu.yygh.order.mapper.OrderInfoMapper;
import com.atguigu.yygh.order.service.OrderInfoService;
import com.atguigu.yygh.order.service.PaymentService;
import com.atguigu.yygh.order.service.WeiPayService;
import com.atguigu.yygh.order.utils.HttpRequestHelper;
import com.atguigu.yygh.user.client.PatientFeignClient;
import com.atguigu.yygh.vo.hosp.ScheduleOrderVo;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderCountQueryVo;
import com.atguigu.yygh.vo.order.OrderCountVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.atguigu.yygh.vo.order.OrderQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2023-10-01
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private ScheduleFeignClient scheduleFeignClient;

    @Autowired
    private PatientFeignClient patientFeignClient;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private WeiPayService weiPayService;

    @Autowired
    private PaymentService paymentService;

    @Override
    public Long submitOrder(String scheduleId, Long patientId) {
        //1.先根据scheduleId获取医生排班信息
        ScheduleOrderVo scheduleOrderVo = scheduleFeignClient.getScheduleVoById(scheduleId);
        if(new DateTime(scheduleOrderVo.getStopTime()).isBeforeNow()){
             throw new YyghException(20001,"预约时间已经过期！！！！");

        }
        //2.先根据patientId获取就诊人信息
        Patient patient = patientFeignClient.getPatientById(patientId);
        //3.从平台请求第三方医院，确认当前用户能否挂号
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("hoscode",scheduleOrderVo.getHoscode());
        paramMap.put("depcode",scheduleOrderVo.getDepcode());
        paramMap.put("hosScheduleId",scheduleOrderVo.getHosScheduleId());
        paramMap.put("reserveDate",scheduleOrderVo.getReserveDate());
        paramMap.put("reserveTime",scheduleOrderVo.getReserveTime());
        paramMap.put("amount",scheduleOrderVo.getAmount());

        JSONObject jsonObject = HttpRequestHelper.sendRequest(paramMap, "http://localhost:9998/order/submitOrder");

        if(jsonObject!=null && jsonObject.getInteger("code")==200){
            //3.2 如果返回能直接挂号，就把医生排班信息，就诊人信息，以及第三方医院返回的信息都添加到order_info中

            JSONObject data = jsonObject.getJSONObject("data");

            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setUserId(patient.getUserId());
            orderInfo.setOutTradeNo(System.currentTimeMillis()+""+new Random().nextInt(100));
            orderInfo.setHoscode(scheduleOrderVo.getHoscode());
            orderInfo.setHosname(scheduleOrderVo.getHosname());
            orderInfo.setDepcode(scheduleOrderVo.getDepcode());
            orderInfo.setDepname(scheduleOrderVo.getDepname());
            orderInfo.setTitle(scheduleOrderVo.getTitle());
            orderInfo.setReserveDate(scheduleOrderVo.getReserveDate());
            orderInfo.setReserveTime(scheduleOrderVo.getReserveTime());
            orderInfo.setScheduleId(scheduleOrderVo.getHosScheduleId());
            orderInfo.setPatientId(patient.getId());
            orderInfo.setPatientName(patient.getName());
            orderInfo.setPatientPhone(patient.getPhone());

            orderInfo.setHosRecordId(data.getString("hosRecordId"));
            orderInfo.setNumber(data.getInteger("number"));
            orderInfo.setFetchAddress(data.getString("fetchAddress"));
            orderInfo.setFetchTime(data.getString("fetchTime"));

            orderInfo.setAmount(scheduleOrderVo.getAmount());
            orderInfo.setQuitTime(scheduleOrderVo.getQuitTime());
            orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus());

            baseMapper.insert(orderInfo);

             //3.3 更新平台上对应医生的剩余可预约数
            OrderMqVo orderMqVo = new OrderMqVo();
            orderMqVo.setScheduleId(scheduleId);
            int reservedNumber = data.getIntValue("reservedNumber");
            int availableNumber = data.getIntValue("availableNumber");

            orderMqVo.setReservedNumber(reservedNumber);
            orderMqVo.setAvailableNumber(availableNumber);

            MsmVo msmVo = new MsmVo();
            msmVo.setPhone(patient.getPhone());
            msmVo.setTemplateCode("你已经预约了${time}的${name}医生的号，请及时就诊！！");
            Map<String,Object> msmMap = new HashMap<>();
            msmMap.put("time",scheduleOrderVo.getReserveDate()+""+scheduleOrderVo.getReserveTime());
            msmMap.put("name","xxx");
            msmVo.setParam(msmMap);
            orderMqVo.setMsmVo(msmVo);
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER,MqConst.ROUTING_ORDER,orderMqVo);

            //3.4 给就诊人发送短信提醒
            return orderInfo.getId();
        }else{
            //3.1 如果返回不能挂号，就直接抛出异常
            throw new YyghException(20001, "号源已满！！！");

        }
    }

    @Override
    public Page<OrderInfo> getOrderInfoPage(Integer pageNum, Integer pageSize, OrderQueryVo orderQueryVo) {
        Page page = new Page(pageNum,pageSize);
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();

        Long userId = orderQueryVo.getUserId();
        String outTradeNo = orderQueryVo.getOutTradeNo();
        String keyword = orderQueryVo.getKeyword();
        Long patientId = orderQueryVo.getPatientId();
        String orderStatus = orderQueryVo.getOrderStatus();
        String reserveDate = orderQueryVo.getReserveDate();
        String createTimeBegin = orderQueryVo.getCreateTimeBegin();
        String createTimeEnd = orderQueryVo.getCreateTimeEnd();

        if(!StringUtils.isEmpty(userId)){
            queryWrapper.eq("user_id",userId);
        }

        if(!StringUtils.isEmpty(outTradeNo)){
            queryWrapper.eq("out_trade_no",outTradeNo);
        }

        if(!StringUtils.isEmpty(keyword)){
            queryWrapper.like("hosname",keyword);
        }

        if(!StringUtils.isEmpty(patientId)){
            queryWrapper.eq("patient_id",patientId);
        }

        if(!StringUtils.isEmpty(orderStatus)){
            queryWrapper.eq("order_status",orderStatus);
        }

        if(!StringUtils.isEmpty(reserveDate)){
            queryWrapper.ge("reserve_date",reserveDate);
        }

        if(!StringUtils.isEmpty(createTimeBegin)){
            queryWrapper.ge("create_time",createTimeBegin);
        }

        if(!StringUtils.isEmpty(createTimeEnd)){
            queryWrapper.le("create_time",createTimeEnd);
        }

        Page<OrderInfo> page1 = baseMapper.selectPage(page,queryWrapper);
        page1.getRecords().parallelStream().forEach(item->{
            this.packOrderInfo(item);
        });
        return page1;
    }

    @Override
    public OrderInfo detail(Long orderId) {
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        this.packOrderInfo(orderInfo);
        return orderInfo;
    }

    @Override
    public void cancelOrder(Long orderId) {
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        DateTime quitTime = new DateTime(orderInfo.getQuitTime());

        //1.确定当前取消预约的时间 和 挂号订单的取消预约截止时间 对比，当前时间是否已经超过了 挂号订单的取消预约时间：
            //如果超过了，则直接抛出异常 ，不让用户取消
        if(quitTime.isBeforeNow()){
            throw new YyghException(20001,"超过了取消预约截止时间！！！");
        }
            //如果没有超过 ，子继续往下执行
        Map<String,Object> hospParamMap = new HashMap<>();
        hospParamMap.put("hoscode",orderInfo.getHoscode());
        hospParamMap.put("hosRecordId",orderInfo.getHosRecordId());
        //2.从平台请求第三方医院，通知第三方医院，该用户已经取消
        JSONObject jsonObject = HttpRequestHelper.sendRequest(hospParamMap, "http://localhost:9998/order/updateCancelStatus");

        //2.1 第三方医院如果不同意取消：抛出异常，不能取消
        if(jsonObject == null || jsonObject.getIntValue("code")!=200){
            throw new YyghException(20001,"取消失败！！！");
        }
            //2.2 第三方医院如果同意取消： 继续执行
        //3.判断用户是否对当前挂号订单是否已经支付
        if(orderInfo.getOrderStatus()==OrderStatusEnum.PAID.getStatus()){
            //3.1 如果已支付，退款
            boolean flag = weiPayService.refund(orderId);
            if(!flag){
                throw new YyghException(20001,"退款失败！！！");
            }
        }
            //3.2 如果未支付，继续往下执行
        //4.更新订单的状态 及 支付记录表单支付状态
        orderInfo.setOrderStatus(OrderStatusEnum.CANCLE.getStatus());
        baseMapper.updateById(orderInfo);

        UpdateWrapper<PaymentInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("order_id",orderInfo.getId());
        updateWrapper.set("payment_status", PaymentStatusEnum.REFUND.getStatus());
        paymentService.update(updateWrapper);

        //5.更新医生的剩余可预约数的信息
        OrderMqVo orderMqVo = new OrderMqVo();
        orderMqVo.setScheduleId(orderInfo.getScheduleId());

        MsmVo msmVo = new MsmVo();
        msmVo.setPhone(orderInfo.getPatientPhone());
        msmVo.setTemplateCode("xxxx......");
        msmVo.setParam(null);

        orderMqVo.setMsmVo(msmVo);
        //6.给就诊人发送短信提示：
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER,MqConst.ROUTING_ORDER,orderMqVo);
    }

    @Override
    public void patientRemind() {
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("reserve_date",new DateTime().toString("yyyy-MM-dd"));
        queryWrapper.ne("order_status",-1);
        List<OrderInfo> orderInfos = baseMapper.selectList(queryWrapper);
        for (OrderInfo orderInfo : orderInfos) {
            //短信提示
            MsmVo msmVo = new MsmVo();
            msmVo.setPhone(orderInfo.getPatientPhone());
            String reserveDate = new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd") + (orderInfo.getReserveTime()==0 ? "上午": "下午");
            Map<String,Object> param = new HashMap<String,Object>(){{
                put("title", orderInfo.getHosname()+"|"+orderInfo.getDepname()+"|"+orderInfo.getTitle());
                put("reserveDate", reserveDate);
                put("name", orderInfo.getPatientName());
            }};
            msmVo.setParam(param);

            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM,MqConst.ROUTING_MSM_ITEM,msmVo);
        }


    }

    @Override
    public Map<String, Object> statistic(OrderCountQueryVo orderCountQueryVo) {
        List<OrderCountVo> countVoList =  baseMapper.statistic(orderCountQueryVo);
        List<String> dateList = new ArrayList<>();
        List<Integer> countList = new ArrayList<>();
        for (OrderCountVo orderCountVo : countVoList) {
            Integer count = orderCountVo.getCount();
            String reserveDate = orderCountVo.getReserveDate();
            dateList.add(reserveDate);
            countList.add(count);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("dateList",dateList);
        map.put("countList",countList);

        return map;
    }

    private void packOrderInfo(OrderInfo item) {
        item.getParam().put("orderStatusString",OrderStatusEnum.getStatusNameByStatus(item.getOrderStatus()));

    }
}
